package space.misiro.ledgers.keycloak.client.model

import org.keycloak.representations.idm.ClientScopeRepresentation
import org.keycloak.representations.idm.RealmRepresentation
import org.keycloak.representations.idm.RoleRepresentation
import space.misiro.ledgers.middleware.api.domain.Constants
import space.misiro.ledgers.middleware.api.domain.um.UserRoleTO

/**
 * 表示Keycloak领域配置的数据类
 *
 * @param realm 领域名称（唯一标识）
 * @param enable 是否启用该领域（默认true）
 * @param accessTokenLifespan 访问令牌有效期（秒）
 * @param accessTokenLifespanForImplicitFlow 隐式流访问令牌有效期（秒）
 * @param clientSessionIdleTimeout 客户端会话空闲超时（秒）
 * @param clientSessionMaxLifespan 客户端会话最大生存期（秒）
 * @param offlineSessionMaxLifespanEnabled 是否启用离线会话最大生存期（默认true）
 * @param offlineSessionIdleTimeout 离线会话空闲超时（秒）
 * @param offlineSessionMaxLifespan 离线会话最大生存期（秒）
 * @param clientOfflineSessionIdleTimeout 客户端离线会话空闲超时（秒）
 * @param clientOfflineSessionMaxLifespan 客户端离线会话最大生存期（秒）
 * @param registrationAllowed 是否允许用户注册（默认false）
 * @param registrationEmailAsUsername 是否使用邮箱作为用户名（默认false）
 * @param verifyEmail 是否验证用户邮箱（默认true）
 * @param loginWithEmailAllowed 是否允许使用邮箱登录（默认true）
 * @param duplicateEmailsAllowed 是否允许重复邮箱（默认false）
 * @param resetPasswordAllowed 是否允许重置密码（默认true）
 * @param editUsernameAllowed 是否允许修改用户名（默认true）
 * @param smtpServer SMTP服务器配置参数（默认空）
 */
data class KeycloakRealm(
    val realm: String,
    val enable: Boolean = true,
    val accessTokenLifespan: Int,
    val accessTokenLifespanForImplicitFlow: Int,
    val clientSessionIdleTimeout: Int,
    val clientSessionMaxLifespan: Int,
    val offlineSessionMaxLifespanEnabled: Boolean = true,
    val offlineSessionIdleTimeout: Int,
    val offlineSessionMaxLifespan: Int,
    val clientOfflineSessionIdleTimeout: Int,
    val clientOfflineSessionMaxLifespan: Int,
    val registrationAllowed: Boolean = false,
    val registrationEmailAsUsername: Boolean = false,
    val verifyEmail: Boolean = true,
    val loginWithEmailAllowed: Boolean = true,
    val duplicateEmailsAllowed: Boolean = false,
    val resetPasswordAllowed: Boolean = true,
    val editUsernameAllowed: Boolean = true,
    val smtpServer: Map<String, String> = emptyMap()
) {
    /**
     * 简化构造方法（使用登录令牌和离线令牌的统一TTL配置）
     *
     * @param realmName 领域名称
     * @param loginTokenTTL 登录相关令牌的统一有效期（秒）
     * @param offlineTokenTTL 离线相关令牌的统一有效期（秒）
     * @param smtpServer SMTP服务器配置参数
     */
    constructor(realmName: String, loginTokenTTL: Int, offlineTokenTTL: Int, smtpServer: Map<String, String>) : this(
        realm = realmName,
        accessTokenLifespan = loginTokenTTL,
        accessTokenLifespanForImplicitFlow = loginTokenTTL,
        clientSessionIdleTimeout = loginTokenTTL,
        clientSessionMaxLifespan = loginTokenTTL,
        offlineSessionIdleTimeout = offlineTokenTTL,
        offlineSessionMaxLifespan = offlineTokenTTL,
        clientOfflineSessionIdleTimeout = offlineTokenTTL,
        clientOfflineSessionMaxLifespan = offlineTokenTTL,
        smtpServer = smtpServer
    )

    /**
     * 检查当前领域是否不存在于给定领域列表中
     *
     * @param allRealms 现有领域列表（来自Keycloak）
     * @return true表示当前领域不存在于列表中，需要创建
     */
    fun notPresentRealm(allRealms: List<RealmRepresentation>) = allRealms.none { it.realm == realm }

    /**
     * 获取需要新增的客户端作用域列表
     *
     * @param scopes 现有客户端作用域列表
     * @return 过滤出不在系统预定义常量中的客户端作用域
     */
    fun getScopesToAdd(scopes: List<ClientScopeRepresentation>) =
        scopes.map { it.name }.filterNot { it in Constants.ALL_SCOPES }

    /**
     * 获取需要新增的用户角色列表
     *
     * @param roles 现有角色列表
     * @return 过滤出不在系统预定义角色中的角色
     */
    fun getRolesToAdd(roles: List<RoleRepresentation>) =
        roles.map { it.name }.filterNot { it in UserRoleTO.ALL_ROLES }
}
